package com.zl.tby.service.impl;


import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zl.tby.core.base.bean.OptionType;
import com.zl.tby.core.base.bean.TbyPageResult;
import com.zl.tby.core.base.util.HttpUtil;
import com.zl.tby.core.base.util.NetworkImageThumbnailGenerator;
import com.zl.tby.core.base.util.ToolsUtil;
import com.zl.tby.core.common.FileResult;
import com.zl.tby.core.common.R;
import com.zl.tby.dto.TbyAnimalPlantQuery;
import com.zl.tby.model.TbyAnimalPlant;
import com.zl.tby.model.TbyCameraInfo;
import com.zl.tby.model.TbyEducationView;
import com.zl.tby.model.TbySpeciesCategory;
import com.zl.tby.repository.TbyAnimalPlantRepo;
import com.zl.tby.repository.TbySpeciesCategoryRepo;
import com.zl.tby.repository.TbySummarizeDataRepo;
import com.zl.tby.service.ITbyAnimalPlantService;
import com.zl.tby.service.ITbySpeciesCategoryService;
import com.zl.tby.service.ITbySummarizeDataService;
import com.zl.tby.vo.TbyAnimalPlantForm;
import com.zl.tby.vo.TbySpeciesCategoryBean;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Tran;
import org.noear.wood.DbContext;
import org.noear.wood.DbTableQuery;
import org.noear.wood.IPage;
import org.noear.wood.annotation.Db;
import org.noear.wood.impl.IPageImpl;
import org.noear.wood.utils.StringUtils;

import java.io.File;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 动植物管理接口实现类
 * @author sunjiaxing
 * @version 1.0
 * @since 2024/8/7 23:23
 */
@Component
@Slf4j
public class TbyAnimalPlantServiceImpl implements ITbyAnimalPlantService {
    @Db
    private TbyAnimalPlantRepo tbyAnimalPlantRepo;
    @Inject
    private ITbySpeciesCategoryService tbySpeciesCategoryService;
    @Inject
    private ITbySummarizeDataService tbySummarizeDataService;
    @Db
    private TbySpeciesCategoryRepo tbySpeciesCategoryRepo;
    @Db
    private DbContext db;
    @Inject("${server.request.upload-url}")
    private String uploadUrl;
    @Inject("${server.request.system-url}")
    private String systemUrl;
    @Inject("${server.request.temp-url}")
    private String tempUrl;

    @Override
    @Tran
    public R<TbyAnimalPlant> add(TbyAnimalPlantForm form) {
        Long typeLevel = form.getTypeLevel();
        List<TbySpeciesCategory> list = this.tbySpeciesCategoryRepo.selectList(mp -> { mp.whereTrue().and( "id = ?", form.getTypeLevel() ); });
        if(list!=null && list.size()>0){
            if(list.get(0).getParentId()!=0){
                typeLevel = list.get(0).getParentId();
            }
            DbTableQuery dbTableQuery = db.table("tby_animal_plant a")
                    .innerJoin("tby_species_category c").onEq("a.type_level", "c.id")
                    .whereTrue()
                    .andIf(true,"c.id = ?", typeLevel).or("c.parent_id = ?", typeLevel)
                    .andIf(true,"a.is_species = ?", "0");
            try {
                if ("0".equals(form.getIsSpecies()) && dbTableQuery.selectCount() >= 3) {
                    return R.failed("当前系统旗舰物种数量已达上限，无法添加");
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (!checkSponsorshipCount(form.getSponsorship())) {
            return R.failed("最多支持10个冠名物种");
        }
        TbyAnimalPlant entity = form.createEntity();
        entity.setCreateBy(ToolsUtil.getLoginUserId());
        entity.setCreateTime(LocalDateTime.now());
        entity = this.setWZLevel(entity);
        long id = tbyAnimalPlantRepo.insert(entity, true);
        entity.setId(id);
//        this.tbyFileBusinessService.saveAttach(BusinessIdentifyingEnum.MOUNTAIN_PEAK.toString(), id, form.getAttach());
        return R.ok(entity);
    }

    @Override
    @Tran
    public R<TbyAnimalPlant> update(TbyAnimalPlantForm form) {
        Long typeLevel = form.getTypeLevel();
        List<TbySpeciesCategory> list = this.tbySpeciesCategoryRepo.selectList(mp -> { mp.whereTrue().and( "id = ?", form.getTypeLevel() ); });
        if(list!=null && list.size()>0){
            if(list.get(0).getParentId()!=0){
                typeLevel = list.get(0).getParentId();
            }
            DbTableQuery dbTableQuery = db.table("tby_animal_plant a")
                    .innerJoin("tby_species_category c").onEq("a.type_level", "c.id")
                    .whereTrue()
                    .andIf(true,"(c.id = ? or c.parent_id = ?)", new Object[]{typeLevel, typeLevel})
                    .andIf(true,"a.is_species = ?", "0")
                    .andNeq("a.id", form.getId());
            try {
                if ("0".equals(form.getIsSpecies()) && dbTableQuery.selectCount() >= 3) {
                    return R.failed("当前系统旗舰物种数量已达上限，无法添加");
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (!checkSponsorshipCount(form.getSponsorship())) {
            return R.failed("最多支持10个冠名物种");
        }
        TbyAnimalPlant entity = this.get(form.getId());
        if (entity == null) {
            return R.failed("数据不存在");
        }
        form.updateEntity(entity);
        entity.setUpdateBy(ToolsUtil.getLoginUserId());
        entity.setUpdateTime(LocalDateTime.now());
        entity = this.setWZLevel(entity);
        tbyAnimalPlantRepo.updateById(entity, false);
//        this.tbyFileBusinessService.saveAttach(BusinessIdentifyingEnum.MOUNTAIN_PEAK.toString(), entity.getId(), form.getAttach());
        return R.ok(entity);
    }

    private boolean checkSponsorshipCount(Integer sponsorship) {
        if (sponsorship != null && sponsorship.intValue() == 0) {
            return true;
        }
        TbyAnimalPlantQuery query = new TbyAnimalPlantQuery();
        query.setSponsorship(sponsorship);
        List<TbyAnimalPlant> dbList = this.list(query);
        return (dbList != null && dbList.size() >= 10) ? false : true;
    }

    public TbyAnimalPlant setWZLevel(TbyAnimalPlant entity) {
            if(StringUtils.isNotEmpty(entity.getTypeLevels())){
            //把选中数量存到对应分级中
            String[] arr = entity.getTypeLevels().split(",");
            entity.setWzBoundary(BigDecimal.ZERO);
            entity.setWzPhylum(BigDecimal.ZERO);
            entity.setWzCorrect(BigDecimal.ZERO);
            entity.setWzCatalogue(BigDecimal.ZERO);
            entity.setWzSection(BigDecimal.ZERO);
            entity.setWzGenus(BigDecimal.ZERO);
            entity.setWzSpecies(BigDecimal.ZERO);
            for(String item : arr){
                if("1".equals(item)){
                    entity.setWzBoundary(entity.getWzBoundary().add(BigDecimal.ONE));
                } else if("2".equals(item)){
                    entity.setWzPhylum(entity.getWzPhylum().add(BigDecimal.ONE));
                } else if("3".equals(item)){
                    entity.setWzCorrect(entity.getWzCorrect().add(BigDecimal.ONE));
                } else if("4".equals(item)){
                    entity.setWzCatalogue(entity.getWzCatalogue().add(BigDecimal.ONE));
                } else if("5".equals(item)){
                    entity.setWzSection(entity.getWzSection().add(BigDecimal.ONE));
                } else if("6".equals(item)){
                    entity.setWzGenus(entity.getWzGenus().add(BigDecimal.ONE));
                } else if("7".equals(item)){
                    entity.setWzSpecies(entity.getWzSpecies().add(BigDecimal.ONE));
                }
            }

        }
        return  entity;
    }
    @Override
    public TbyAnimalPlant get(Long id) {
        TbyAnimalPlant dto = tbyAnimalPlantRepo.selectById(id);
        TbySpeciesCategory sc = tbySpeciesCategoryRepo.selectById(dto.getTypeLevel());
        if (sc!=null){
            dto.setTypeLevelValue(sc.getCategoryName());
        }
        return dto;
    }

    @Override
    public R<Void> delete(Long id) {
        if(!tbySummarizeDataService.summarizeDataUse(id)){
            return R.failed("此数据被关联引用，不能删除！");
        }else{
            return tbyAnimalPlantRepo.deleteById(id) == 1 ? R.ok() : R.failed("删除失败");
        }
    }

    @Override
    public TbyPageResult<TbyAnimalPlant> page(TbyAnimalPlantQuery query) {
        try {
            DbTableQuery dbTableQuery = db.table("tby_animal_plant a")
                    .leftJoin("tby_species_category c").onEq("a.type_level", "c.id")
                    .whereTrue()
                    .andIf(query.getTypeLevel()!=null,"(c.id = ?", query.getTypeLevel()).orIf(query.getTypeLevel()!=null,"c.parent_id = ?)", query.getTypeLevel())
                    .andIf(StringUtils.isNotEmpty(query.getChName()), "a.ch_name like ?", "%" + query.getChName() + "%")
                    .andIf(StringUtils.isNotEmpty(query.getIsSpecies()), "a.is_species = ?", query.getIsSpecies() )
                    .andIf(StringUtils.isNotEmpty(query.getProtectionLevel()), "a.protection_level = ?",  query.getProtectionLevel())
                    .andIf(StringUtils.isNotEmpty(query.getIucn()), "a.iucn = ?", query.getIucn() )
                    .andIf(StringUtils.isNotEmpty(query.getCites()), "a.cites = ?", query.getCites() )
                    .andIf(query.getLegend() != null, "a.legend = ?", query.getLegend())
                    .andIf(query.getSponsorship() != null, "a.sponsorship = ?", query.getSponsorship() );
            dbTableQuery.limit(query.getOffset(), query.getSize());
            List<TbyAnimalPlant> dataList = dbTableQuery.selectList("a.id id,a.ch_name ch_name,a.ch_pinyin ch_pinyin,a.protection_level protection_level,a.is_species is_species,a.type_level type_level,a.level_names level_names",TbyAnimalPlant.class);
            long total = dbTableQuery.selectCount();
            return new TbyPageResult(new IPageImpl(dataList, total, query.getSize()), query);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<TbyAnimalPlant> list(TbyAnimalPlantQuery query) {
        return this.tbyAnimalPlantRepo.selectList(mp -> {
            mp.whereTrue()
                    .andIf(StringUtils.isNotEmpty(query.getChName()), "ch_name like ?", "%" + query.getChName() + "%")
                    .andIf(query.getTypeLevel()!=null, "type_level = ?", query.getTypeLevel() )
                    .andIf(StringUtils.isNotEmpty(query.getProtectionLevel()), "protection_level = ?",  query.getProtectionLevel())
                    .andIf(StringUtils.isNotEmpty(query.getIsSpecies()), "is_species = ?",  query.getIsSpecies())
                    .andIf(StringUtils.isNotEmpty(query.getIucn()), "iucn = ?", query.getIucn() )
                    .andIf(StringUtils.isNotEmpty(query.getCites()), "cites = ?", query.getCites() )
                    .andIf(query.getLegend() != null, "legend = ?", query.getLegend())
                    .andIf(query.getSponsorship() != null, "sponsorship = ?", query.getSponsorship() );

            if (StringUtils.isNotEmpty(query.getOrder())) {
                mp.orderBy(query.getOrder());
            }
        });
    }

    @Override
    public List<TbyAnimalPlant> overviewList() {
        List<Long> categoryIdList = this.tbySpeciesCategoryService.getUseOverviewIdList();
        if (categoryIdList == null || categoryIdList.size() == 0) {
            return new ArrayList<>();
        }
        return this.tbyAnimalPlantRepo.selectList(mp -> {
            mp.whereIn("type_level", categoryIdList).andEq("is_species", "0");
        });
    }

    @Override
    public List<OptionType> options() {
        List<OptionType> optionTypes = new ArrayList<>();
        OptionType dto = new OptionType("0","是");
        OptionType dto1 = new OptionType("1","否");
        optionTypes.add(dto);
        optionTypes.add(dto1);
        return optionTypes;
    }

    /**
     * 封装物种分类与物种的级联组件数据
     * @return 数据
     */
    @Override
    public List<OptionType> cascaderList() {
        List<TbySpeciesCategory> categoryList = this.tbySpeciesCategoryService.list();
        List<OptionType> optionList = new ArrayList<>();
        for (TbySpeciesCategory entity : categoryList) {
            OptionType optionType = new OptionType("cate_" + entity.getId(), entity.getCategoryName());
            optionType.setParentId("cate_" + entity.getParentId());
            optionList.add(optionType);
        }
        List<TbyAnimalPlant> dbList = this.tbyAnimalPlantRepo.selectList(mp -> { mp.whereTrue(); });
        for (TbyAnimalPlant entity : dbList) {
            OptionType optionType = new OptionType("ap_" + entity.getId(), entity.getChName());
            optionType.setParentId("cate_" + entity.getTypeLevel());
            optionList.add(optionType);
        }
        return OptionType.recurOptions("cate_0", optionList);
    }

    @Override
    public R<Boolean> checkChName(Long id, String chName) {
        if (StringUtils.isEmpty(chName)) {
            return R.ok(false);
        }
        List<TbyAnimalPlant> dbList = this.tbyAnimalPlantRepo.selectList(mp -> {
            mp.whereEq("ch_name", chName);
        });
        for (TbyAnimalPlant data : dbList) {
            if (id == null && data.getChName().equals(chName)) {
                return R.ok(true);
            } else if (id != null && data.getChName().equals(chName) && id.compareTo(data.getId()) != 0) {
                return R.ok(true);
            }
        }
        return R.ok(false);
    }

    @Override
    public void createThumbnail(Long id) {
        if (id != null) {
            TbyAnimalPlant entity = this.get(id);
            if (id != null) {
                createThumbnail(entity);
            }
        } else {
            List<TbyAnimalPlant> dbList = this.tbyAnimalPlantRepo.selectList(mp -> {
                mp.whereEq("thumbnail", null);
            });
            for (TbyAnimalPlant entity : dbList) {
                createThumbnail(entity);
            }
        }
    }

    private void createThumbnail(TbyAnimalPlant entity) {
        try {
            String sourceUrl = systemUrl + entity.getFiles();
            String[] array = ToolsUtil.splitStr(entity.getFiles(), '.');
            String fileSuffix = array[array.length - 1];
            String outputPath1210x955 = tempUrl + entity.getId() + "650x300." + fileSuffix;
            String outputPath235x162 = tempUrl + entity.getId() + "132x103." + fileSuffix;
            NetworkImageThumbnailGenerator.generateThumbnail(sourceUrl, outputPath1210x955, 650, 300, 0.5f);
            NetworkImageThumbnailGenerator.generateThumbnail(sourceUrl, outputPath235x162, 132, 103, 0.5f);
            upload(entity.getId(), outputPath1210x955, 650);
            upload(entity.getId(), outputPath235x162, 132);
            log.info("物种生成缩略图，id = " + entity.getId() + "，生成成功");
        } catch (Exception ex) {
            log.error("物种管理，图片生成缩略图异常：id = " + entity.getId(), ex);
        }
    }

    private void upload(Long id, String outputPath, int size) throws Exception {
        Gson gson = new Gson();
        String uploadResponse = HttpUtil.uploadFile(systemUrl + uploadUrl, outputPath);
        R<FileResult> r = gson.fromJson(uploadResponse, new TypeToken<R<FileResult>>(){}.getType());
        if (r.getCode() != 0) {
            log.error("物种管理，图片生成缩略图异常：id = " + id, r.getMsg());
            return;
        }
        if (StringUtils.isNotEmpty(r.getData().getFileName())) {
            TbyAnimalPlant view = new TbyAnimalPlant();
            view.setId(id);
            if (size == 650) {
                view.setThumbnail("/file/img/" + r.getData().getFileName());
            } else if (size == 132) {
                view.setThumbnailIcon("/file/img/" + r.getData().getFileName());
            }
            this.tbyAnimalPlantRepo.updateById(view, true);
            File file = new File(outputPath);
            file.delete();
        }
    }
}
